package org.example.compnent.Parser;

import cn.hutool.core.text.csv.CsvData;
import cn.hutool.core.text.csv.CsvReader;
import cn.hutool.core.text.csv.CsvRow;
import cn.hutool.core.text.csv.CsvUtil;
import org.example.common.enums.FileParser;
import org.example.common.result.FileParseResult;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.*;
/**
 * CSV解析器,将csv文件解析并封装
 */
@Component
public class CsvParser implements FileParser {
    /**
     * Boolean包装类型可以指示为无状态，用final一经确定不可更改，达到线程安全
     */
    //有无表头
    private final Boolean hasHeader ;
    //构造函数 支持手动传入hasHeader（null为自动识别）
    public CsvParser() {
        this.hasHeader = null;
    }
    public CsvParser(boolean hasHeader) {
        this.hasHeader = hasHeader;// 手动指定（true/false）
    }

    @Override
    public FileParseResult parse(MultipartFile file) throws Exception {
        FileParseResult result = new FileParseResult();
        List<String> headers = new ArrayList<>();
        List<List<Object>> dataRows = new ArrayList<>();
        List<List<String>> allLines = new ArrayList<>(); // 暂存所有行文本，用于自动识别
        int totalRows = 0;
        // 通过 MultipartFile 的输入流解析，避免文件路径问题
        try ( InputStream in =file.getInputStream();
                CsvReader reader= CsvUtil.getReader()
        ){  // Hutool 的 CsvReader 会自动处理 CSV 格式
            //CsvData data=reader.read(FileUtil.file("文件路径"));
            //这样需要传入文件路径，所以选择输入流
            // 修正：将 InputStream 转为 InputStreamReader 并指定 UTF-8 编码
            CsvData data = reader.read(new InputStreamReader(in, StandardCharsets.UTF_8));

            List<CsvRow> rows = data.getRows();
            //收集所有非空的原始字段列表
            for (CsvRow csvRow : rows) {//遍历行
                List<String> fields = csvRow.getRawList();// 获取每行的字段列表（已处理引号、转义）
                if(!csvRow.isEmpty()){
                    allLines.add(fields);
                    totalRows++;
                }
            }
        }catch (Exception e) {
            result.setSuccess(false);
            result.setErrorMessage("读取文件失败：" + e.getMessage());
            return result;
        }

        if (allLines.isEmpty()) {
            result.setSuccess(true);
            result.setErrorMessage("文件内容为空");
            return result;
        }
        // 2. 确定是否有表头（优先使用手动参数，否则自动识别）
        /*    自动识别
                  if (hasHeader != null) {
                      actualHasHeader = hasHeader; // 手动指定
                  } else {
                      actualHasHeader = autoDetectHeader(allLines); // 自动识别
                  }
                  写成lambd表达式actualHasHeader = Objects.requireNonNullElseGet(hasHeader, () -> autoDetectHeader(allLines)); // 手动指定

         */
        boolean actualHasHeader = (hasHeader != null) ? hasHeader : autoDetectHeader(allLines);
        // 解析表头和数据行
        if (actualHasHeader) {
            // 第一行为表头
            headers = allLines.get(0);
            // 从第二行开始解析数据
            for (int i = 1; i < allLines.size(); i++) {
                dataRows.add(convertToDataRow(allLines.get(i)));
            }
        } else {
            // 无表头，所有行都是数据
            headers = null;
            for (List<String> line : allLines) {
                dataRows.add(convertToDataRow(line));
            }
        }

        // 4. 填充结果
        result.setHeaders(headers);
        result.setDataRows(dataRows);
        result.setSuccess(true);
        result.setTotalRows(totalRows);
        result.setValidDataRows(dataRows.size());
        return result;
    }

    // 核心：自动识别是否有表头
    private boolean autoDetectHeader(List<List<String>> allLines) {
        // 条件1：至少有2行（表头+至少1行数据）
        if (allLines.size() < 2) {
            return false; // 只有1行，默认无表头
        }

        // 取第一行（候选表头）和第二行（候选数据）
        List<String> firstLine = allLines.get(0);
        List<String> secondLine = allLines.get(1);

        // 条件2：表头行的字段更可能是纯字符串（不含数字），数据行可能包含数字
        return countNumberFields(firstLine) < countNumberFields(secondLine);
    }

//    // 辅助：分割CSV行（处理引号包裹的逗号，简化版）
//    private String[] splitCsvLine(List<String> line) {
//        // 实际项目建议用OpenCSV的CSVParser，这里简化处理
//        return line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)");
//    }

    // 辅助：将CSV行转换为数据行（自动转换类型）
    private List<Object> convertToDataRow(List<String> line) {
        List<Object> row = new ArrayList<>();
        for (String field : line) { // 直接使用Hutool解析好的字段
            row.add(convertField(field));
        }
        return row;
    }

    // 转换单个字段的类型（字符串→数字/布尔值）
    private Object convertField(String field) {
        field = field.replace("\"", "").trim(); // 去除引号和空格
        try {
            if (field.contains(".")) {
                return Double.parseDouble(field);
            } else {
                return Long.parseLong(field);
            }
        } catch (NumberFormatException e) {
            if ("true".equalsIgnoreCase(field)) return true;
            if ("false".equalsIgnoreCase(field)) return false;
            return field; // 无法转换则保留字符串
        }
    }


    // 辅助：统计一行中数字类型的字段数量
    private long countNumberFields(List<String> fields) {
        return fields.stream()
                .map(String::trim)
                .filter(field -> {
                    try {
                        Double.parseDouble(field);
                        return true;
                    } catch (NumberFormatException e) {
                        return false;
                    }
                })
                .count();
    }

}
